package com.iplay.java8inaction.chapter11.node112;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
 * 商店
 *
 * @author dangwu
 * @since 2021/10/20 10:47 上午
 */
public class Shop extends Delay {
    private final String shopName;
    public Shop(String shopName){
        this.shopName = shopName;
    }
    /**
     * 同步调用方法
     *
     * @param product
     * @return
     */
    public double getPrice(String product) {
        //查库等逻辑
        return calculatePrice(product);
    }

    private double calculatePrice(String product) {
        delay();
        return random.nextDouble() * product.charAt(0) + product.charAt(1);
    }

    public Future<Double> getPriceAsync(String product) {
        //创建CompletableFuture对象，它会包含计算的结果
        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
        //在另一个线程中以异步方式执行计算
        new Thread(() -> {
            double price = calculatePrice(product);
            //需长时间计算的任务结束并得出结果时，设置Future的返回值
            futurePrice.complete(price);
        }).start();
        //无需等待还没结束的计算，直接返回Future对象
        return futurePrice;
    }
    public Future<Double> getPriceAsync2(String product) {
        //创建CompletableFuture对象，它会包含计算的结果
        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
        //在另一个线程中以异步方式执行计算
        new Thread(() -> {
            try {
                double price = calculatePrice(product);
                //需长时间计算的任务结束并得出结果时，设置Future的返回值
                futurePrice.complete(price);
            } catch (Exception e) {
                futurePrice.completeExceptionally(e);
            }
        }).start();
        //无需等待还没结束的计算，直接返回Future对象
        return futurePrice;
    }

    public Future<Double> getPriceAsync3(String product) {
        //使用工厂方法supplyAsync创建CompletableFuture对象,不用关注实现细节
        return CompletableFuture.supplyAsync(()->calculatePrice(product));
    }

    public static void main(String[] args) {
        Shop shop = new Shop("BestShop");
        long start = System.nanoTime();
        // ←─查询商店，试图取得商品的价格
        Future<Double> futurePrice = shop.getPriceAsync("my favorite product");
        long invocationTime = ((System.nanoTime() - start) / 1_000_000);
        System.out.println("Invocation returned after " + invocationTime
                + " msecs");
// 执行更多任务，比如查询其他商店
        doSomethingElse();
// 在计算商品价格的同时
        try {
            long startGetTime = System.nanoTime();
            //←─从Future对象中读取价格，如果价格未知，会发生阻塞
            double price = futurePrice.get();
            System.out.println("Price get time "+ ((System.nanoTime() - startGetTime) / 1_000_000)+" msecs");
            System.out.printf("Price is %.2f%n", price);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        long retrievalTime = ((System.nanoTime() - start) / 1_000_000);
        System.out.println("Price returned after " + retrievalTime + " msecs");
    }
}